'''
gevent 协程库的使用
gevent 是一个基于协程的 Python 网络库，它可以让我们在单线程中实现并发 IO。
gevent 提供了一个 gevent 模块，它包含了一些常用的函数和类，例如：

gevent.spawn()：创建一个协程对象
gevent.joinall()：等待所有协程对象执行完毕
gevent.sleep()：让当前协程暂停执行一段时间
gevent.getcurrent()：获取当前协程对象
gevent.kill()：杀死一个协程对象
gevent.wait()：等待多个协程对象执行完毕
gevent.timeout()：设置一个超时时间
gevent.lock()：创建一个锁对象
gevent.event()：创建一个事件对象
gevent.queue()：创建一个队列对象
gevent.pool()：创建一个协程池对象
gevent.monkey.patch_all()：将标准库中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_socket()：将 socket 模块中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_ssl()：将 ssl 模块中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_thread()：将 thread 模块中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_os()：将 os 模块中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_select()：将 select 模块中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_subprocess()：将 subprocess 模块中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_time()：将 time 模块中的阻塞函数替换为 gevent 中的非阻塞函数
gevent.monkey.patch_all()：将所有标准库中的阻塞函数替换为 gevent 中的非阻塞函数


gevent 和 greenlet 都是用于实现 Python 协程编程的工具，但它们在功能、使用场景等方面存在一些差异，下面为你详细比较：

1. 核心概念
greenlet：是一个轻量级的协程实现库，它提供了基本的协程切换机制。greenlet 核心是 greenlet 对象，
代表一个可以暂停和恢复执行的上下文，通过 switch() 方法在不同的 greenlet 对象之间切换执行。

gevent：基于 greenlet 构建，是一个高级的并发编程库。它不仅提供了协程的基本功能，
还集成了事件循环、网络 I/O 等功能，能够自动处理协程之间的调度和切换。

2. 功能特性
greenlet：功能相对基础，主要聚焦于协程的创建和手动切换。开发者需要自己编写代码来控制协程的调度，实现复杂的并发逻辑。
gevent：功能丰富，除了协程管理，还提供了很多高级功能，如：
自动切换：gevent 可以在遇到 I/O 操作时自动切换协程，无需手动干预。
网络支持：内置了对网络编程的支持，包括 TCP、UDP、HTTP 等协议，方便开发者进行网络应用开发。
标准库替换：gevent.monkey 模块可以将标准库中的阻塞函数替换为非阻塞函数，使得现有的同步代码可以无缝转换为异步代码。

3. 使用复杂度
greenlet：使用起来相对复杂，需要开发者对协程的调度和切换有深入的理解。手动管理协程的生命周期和切换逻辑，容易出错。
gevent：使用起来更加简单，提供了高级的 API，使得开发者可以像编写同步代码一样编写异步程序。
例如，使用 gevent.spawn() 创建协程，gevent.joinall() 等待协程完成。

4. 性能表现
greenlet：由于其轻量级的特性，在简单的协程切换场景下，性能开销较小。但在处理复杂的并发任务时，手动管理协程可能会导致性能瓶颈。
gevent：在处理大量并发 I/O 任务时，性能表现出色。通过自动切换协程和高效的事件循环机制，能够充分利用系统资源，提高程序的并发处理能力。

5. 适用场景
greenlet：适用于对协程调度有精细控制需求的场景，或者需要实现自定义协程调度算法的场景。例如，在一些特定的算法实现中，需要手动控制协程的执行顺序。
gevent：适用于大多数并发编程场景，特别是网络编程和 I/O 密集型应用。例如，Web 服务器、爬虫程序、消息队列处理等。


'''

import gevent

# 定义一个协程函数
def task(n,name):
    for i in range(n):
        print(f"协程{name}: {gevent.getcurrent()} 执行第 {i} 次")
        # 模拟耗时操作，使用 gevent.sleep 而不是 time.sleep
        gevent.sleep(1)  # 暂停 1 秒，切换到其他协程，直到时间片用完再继续执行

# 创建协程对象
g1 = gevent.spawn(task, 3,'yejing')  # 传递参数,task 函数会被调用,并传递参数 3
g2 = gevent.spawn(task, 3,'zhangsan')  # 传递参数,task 函数会被调用,并传递参数 3
g3 = gevent.spawn(task, 3,'aaa')  # 传递参数,task 函数会被调用,并传递参数 3

# 等待所有协程完成
gevent.joinall([g1, g2, g3])


# 没有任务切换的结果
# 协程yejing: <Greenlet at 0x1cab4b4f600: task(3, 'yejing')> 执行第 0 次
# 协程zhangsan: <Greenlet at 0x1cab5208a40: task(3, 'zhangsan')> 执行第 0 次
# 协程aaa: <Greenlet at 0x1cab5166980: task(3, 'aaa')> 执行第 0 次
# 协程yejing: <Greenlet at 0x1cab4b4f600: task(3, 'yejing')> 执行第 1 次
# 协程zhangsan: <Greenlet at 0x1cab5208a40: task(3, 'zhangsan')> 执行第 1 次
# 协程aaa: <Greenlet at 0x1cab5166980: task(3, 'aaa')> 执行第 1 次
# 协程yejing: <Greenlet at 0x1cab4b4f600: task(3, 'yejing')> 执行第 2 次
# 协程zhangsan: <Greenlet at 0x1cab5208a40: task(3, 'zhangsan')> 执行第 2 次
# 协程aaa: <Greenlet at 0x1cab5166980: task(3, 'aaa')> 执行第 2 次


# 有任务切换的结果
# 协程yejing: <Greenlet at 0x1cab4b4f600: task(3, 'yejing')> 执行第 0 次
# 协程zhangsan: <Greenlet at 0x1cab5208a40: task(3, 'zhangsan')> 执行第 0 次
# 协程aaa: <Greenlet at 0x1cab5166980: task(3, 'aaa')> 执行第 0 次
# 协程yejing: <Greenlet at 0x1cab4b4f600: task(3, 'yejing')> 执行第 1 次
# 协程zhangsan: <Greenlet at 0x1cab5208a40: task(3, 'zhangsan')> 执行第 1 次
# 协程aaa: <Greenlet at 0x1cab5166980: task(3, 'aaa')> 执行第 1 次
# 协程yejing: <Greenlet at 0x1cab4b4f600: task(3, 'yejing')> 执行第 2 次
# 协程zhangsan: <Greenlet at 0x1cab5208a40: task(3, 'zhangsan')> 执行第 2 次
# 协程aaa: <Greenlet at 0x1cab5166980: task(3, 'aaa')> 执行第 2 次


